using CoreManager.Repository.Repositories;
using CoreManager.Models.DTOs;
using CoreManager.Models.Entities;
using CoreManager.Core.Caching;
using System.Text.Json;
using Microsoft.AspNetCore.Http;
using CoreManager.Common;

namespace CoreManager.Services.Auth
{
    /// <summary>
    /// 认证服务实现
    /// </summary>
    public class AuthService : IAuthService
    {
        private readonly IRepository<User> _userRepository;
        private readonly IRepository<Role> _roleRepository;
        private readonly IRepository<UserRole> _userRoleRepository;
        private readonly IJwtService _jwtService;
        private readonly ICacheService _cacheService;

       

        public AuthService(
            IRepository<User> userRepository,
            IRepository<Role> roleRepository,
            IRepository<UserRole> userRoleRepository,
            IJwtService jwtService,
            ICacheService cacheService)
        {
            _userRepository = userRepository;
            _roleRepository = roleRepository;
            _userRoleRepository = userRoleRepository;
            _jwtService = jwtService;
            _cacheService = cacheService;
        }

        public async Task<LoginResultDto?> LoginAsync(LoginDto loginDto)
        {
            // 查找用户
            var user = await _userRepository.GetAsync(u => u.UserName == loginDto.UserName);
            if (user == null)
            {
                return null;
            }

            // 验证密码
            if (!BCrypt.Net.BCrypt.Verify(loginDto.Password, user.Password))
            {
                return null;
            }

            // 检查用户状态
            if (user.Status != 1)
            {
                throw new UnauthorizedAccessException("用户已被禁用");
            }

            // 获取用户角色
            var userRoles = await _userRoleRepository.GetListAsync(ur => ur.UserId == user.Id);
            var roleIds = userRoles.Select(ur => ur.RoleId).ToList();
            var roles = await _roleRepository.GetListAsync(r => roleIds.Contains(r.Id));

            // 构建用户信息
            var userInfo = new UserInfoDto
            {
                Id = user.Id,
                UserName = user.UserName,
                RealName = user.RealName,
                Email = user.Email,
                PhoneNumber = user.Phone,
                AvatarUrl = user.Avatar,
                Roles = roles.Select(r => r.RoleCode).ToList(),
                LastLoginTime = user.LastLoginTime
            };

            // 生成令牌
            var accessToken = _jwtService.GenerateAccessToken(userInfo);
            var refreshToken = _jwtService.GenerateRefreshToken();

            // 保存刷新令牌到Redis
            var refreshTokenData = new
            {
                UserId = user.Id,
                UserName = user.UserName,
                CreatedAt = DateTime.UtcNow,
                ClientIp = "", // TODO: 获取客户端IP
                UserAgent = "" // TODO: 获取用户代理
            };

            var refreshTokenKey = CacheConstants.USER_REFRESH_TOKEN + refreshToken;
            var refreshTokenJson = JsonSerializer.Serialize(refreshTokenData);
            
            // 在Redis中存储刷新令牌，设置7天过期时间
            await _cacheService.SetAsync(refreshTokenKey, refreshTokenJson, CacheConstants.REFRESH_TOKEN_EXPIRY);

            // 更新登录信息
            user.LastLoginTime = DateTime.Now;
            //.LastLoginIp = ""; // TODO: 获取客户端IP
            await _userRepository.UpdateAsync(user);

            return new LoginResultDto
            {
                UserId = user.Id,
                UserName = user.UserName,
                AccessToken = accessToken,
                RefreshToken = refreshToken,
                ExpiresIn = 60 * 60 // 60分钟，单位为秒
            };
        }

        /// <summary>
        /// 刷新访问令牌
        /// </summary>
        /// <param name="refreshToken">刷新令牌</param>
        /// <returns>新的访问令牌和刷新令牌</returns>
        public async Task<LoginResultDto?> RefreshTokenAsync(string refreshToken)
        {
            // 验证刷新令牌格式
            if (string.IsNullOrWhiteSpace(refreshToken))
            {
                throw new ArgumentException("刷新令牌不能为空");
            }

            // 从Redis查找刷新令牌
            var refreshTokenKey = CacheConstants.USER_REFRESH_TOKEN + refreshToken;
            var refreshTokenJson = await _cacheService.GetAsync<string>(refreshTokenKey);

            if (string.IsNullOrEmpty(refreshTokenJson))
            {
                throw new UnauthorizedAccessException("无效的刷新令牌或令牌已过期");
            }

            // 反序列化令牌数据
            var refreshTokenData = JsonSerializer.Deserialize<RefreshTokenData>(refreshTokenJson);
            if (refreshTokenData == null)
            {
                throw new UnauthorizedAccessException("刷新令牌数据格式错误");
            }

            // 获取用户信息
            var user = await _userRepository.GetByIdAsync(refreshTokenData.UserId);
            if (user == null)
            {
                throw new UnauthorizedAccessException("用户不存在或已被删除");
            }

            // 获取用户角色
            var userRoles = await _userRoleRepository.GetListAsync(ur => ur.UserId == user.Id);
            var roleIds = userRoles.Select(ur => ur.RoleId).ToList();
            var roles = await _roleRepository.GetListAsync(r => roleIds.Contains(r.Id));

            var userInfo = new UserInfoDto
            {
                Id = user.Id,
                UserName = user.UserName,
                RealName = user.RealName,
                Email = user.Email,
                PhoneNumber = user.Phone,
                AvatarUrl = user.Avatar,
                Roles = roles.Select(r => r.RoleCode).ToList(),
                LastLoginTime = user.LastLoginTime
            };

            // 生成新的访问令牌和刷新令牌
            var newAccessToken = _jwtService.GenerateAccessToken(userInfo);
            var newRefreshToken = _jwtService.GenerateRefreshToken();

            // 删除旧的刷新令牌
            await _cacheService.RemoveAsync(refreshTokenKey);

            // 保存新的刷新令牌到Redis
            var newRefreshTokenData = new
            {
                UserId = user.Id,
                UserName = user.UserName,
                CreatedAt = DateTime.UtcNow,
                ClientIp = "", // TODO: 获取客户端IP
                UserAgent = "" // TODO: 获取用户代理
            };

            var newRefreshTokenKey = CacheConstants.USER_REFRESH_TOKEN + newRefreshToken;
            var newRefreshTokenJson = JsonSerializer.Serialize(newRefreshTokenData);
            
            // 在Redis中存储新的刷新令牌，设置7天过期时间
            await _cacheService.SetAsync(newRefreshTokenKey, newRefreshTokenJson, CacheConstants.REFRESH_TOKEN_EXPIRY);

            return new LoginResultDto
            {
                UserId = user.Id,
                UserName = user.UserName,
                AccessToken = newAccessToken,
                RefreshToken = newRefreshToken,
                ExpiresIn = 60 * 60 // 60分钟，单位为秒
            };
        }

        /// <summary>
        /// 用户登出
        /// </summary>
        /// <param name="userId">用户ID</param>
        /// <returns>是否成功</returns>
        public async Task<bool> LogoutAsync(int userId)
        {
            // 删除内存token
            var removeAsync = await _cacheService.RemoveAsync(CacheConstants.USER_TOKEN_PREFIX + userId);
            return removeAsync;
        }

        public async Task<UserInfoDto?> GetCurrentUserAsync(int userId)
        {
            var user = await _userRepository.GetByIdAsync(userId);
            if (user == null)
            {
                return null;
            }

            // 获取用户角色
            var userRoles = await _userRoleRepository.GetListAsync(ur => ur.UserId == user.Id);
            var roleIds = userRoles.Select(ur => ur.RoleId).ToList();
            var roles = await _roleRepository.GetListAsync(r => roleIds.Contains(r.Id));

            return new UserInfoDto
            {
                Id = user.Id,
                UserName = user.UserName,
                RealName = user.RealName,
                Email = user.Email,
                Phone = user.Phone,
                Avatar = user.Avatar,
                Roles = roles.Select(r => r.RoleCode).ToList(),
                Permissions = []
            };
        }

        public async Task<bool> ChangePasswordAsync(int userId, string oldPassword, string newPassword)
        {
            var user = await _userRepository.GetByIdAsync(userId);
            if (user == null)
            {
                return false;
            }

            // 验证旧密码
            if (!BCrypt.Net.BCrypt.Verify(oldPassword, user.Password))
            {
                return false;
            }

            // 更新密码
            user.Password = BCrypt.Net.BCrypt.HashPassword(newPassword);
            user.UpdateTime = DateTime.Now;
            
            return await _userRepository.UpdateAsync(user);
        }
    }
}